﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Core.Model;
using DapperExtensions;
using DapperExtensions.Mapper;
using log4net;

namespace DataServer.Dao
{
    public class DataItemDao : BaseDao<DataItem>
    {
        private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private static DataItemMapper _dataItemMapper;

        public DataItemDao()
        {
            if (_dataItemMapper == null)
            {
                _dataItemMapper = new DataItemMapper();
            }
        }

        protected override string GetTableName()
        {
            if (_dataItemMapper != null)
                return _dataItemMapper.TableName;
            return "data_item";
        }

        public DataItem GetEntityById(string id)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<DataItem>(f => f.Id, Operator.Eq, id);
                DataItem dataItem = result?.Connection.Get<DataItem>(predicate);
                return dataItem;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public Device GetDeviceById(string id)
        {
            ConnectResult result = null;
            try
            {
                if (string.IsNullOrEmpty(id)) return null;
                result = OpenDbConnection();
                string sql = $"SELECT a.* from device a,(SELECT * from {GetTableName()} WHERE Id='{id}') b WHERE a.Id = b.DeviceId";
                List<Device> devices = result?.Connection.GetList<Device>(sql);
                if (devices != null && devices.Count > 0) return devices[0];
                return null;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }
        /// <summary>
        /// 从数据获取数据项 组装成实时值对象（仅用于初始化）
        /// </summary>
        /// <returns></returns>
        public  List<RealTimeData> GetAllDataItems()
        {
            ConnectResult result = null;
            try
            {
                string sql = "SELECT a.Id,a.Name,b.Name as ParentName,0 as Value,\'2018-01-01 00:00:00\' as UpdateTime FROM data_item a,device b WHERE a.DeviceId = b.Id";
                result = OpenDbConnection();
                return result?.Connection.GetList<RealTimeData>(sql).ToList();
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public DataItem GetEntityByName(string name)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<DataItem>(f => f.Name, Operator.Eq, name);
                DataItem dataItem = result?.Connection.Get<DataItem>(predicate);
                return dataItem;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public List<DataItem> GetDataItemsByDevId(string devId,bool storageFilter = false)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicateGroup = new PredicateGroup { Operator = GroupOperator.And, Predicates = new List<IPredicate>() };
                predicateGroup.Predicates.Add(Predicates.Field<DataItem>(f => f.DeviceId, Operator.Eq, devId));
                if (storageFilter)
                    predicateGroup.Predicates.Add(Predicates.Field<DataItem>(f => f.IsStorage, Operator.Eq, true));
                IList<ISort> sort = new List<ISort>();
                sort.Add(new Sort { PropertyName = "Position",Ascending = true});
                IEnumerable<DataItem> dataItems = result?.Connection.GetList<DataItem>(predicateGroup, sort);
                return dataItems?.ToList();
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public List<DataItem> GetReportDataByDevIds(string devIds)
        {
            if (devIds == null || devIds.Length == 0)
                return null;
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                string sql = $"SELECT * FROM {_dataItemMapper.TableName} WHERE Category=2 and DeviceId IN({devIds})";
                IEnumerable<DataItem> dataItems = result?.Connection.GetList<DataItem>(sql);
                return dataItems?.ToList();
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public bool DeleteDataItemsByDeviceId(string devId)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<DataItem>(f => f.DeviceId, Operator.Eq, devId);
                return result.Connection.Delete<DataItem>(predicate);
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return false;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }



    }
    public sealed class DataItemMapper : ClassMapper<DataItem>
    {
        public DataItemMapper()
        {
            Table("data_item");
            Map(x => x.Id).Key(KeyType.Assigned);
            Map(x => x.Value).Ignore();
            Map(x => x.CurValue).Ignore();
            Map(x => x.UpdateTime).Ignore();
            Map(x => x.TagObject).Ignore();
            Map(x => x.LastStoreTime).Ignore(); 
            //Ignore this property entirely
            //optional, map all other columns
            AutoMap();
        }
    }
}
